/**
 * 
 */
package com.imonsoft.common.util;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.core.CollectionFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 * 
 * @author LiQianHui
 * @date 2013-04-17
 * @version 2013
 */
public abstract class DBUtil {

	/**
	 * Set the transaction rollback-only. 仅用于Spring事务控制范围内!
	 */
	public static void setRollbackOnly() {
		TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
	}

	/**
	 * 参rs2list(ResultSet rs)
	 * 
	 * @param object
	 * @return
	 * @throws SQLException
	 */
	public static List<Map<String, String>> rs2list(Object object) throws SQLException {
		if (object instanceof ResultSet) {
			ResultSet rs = (ResultSet) object;
			return rs2list(rs);
		} else {
			return null;
		}
	}

	/**
	 * 将ResultSet封装入List和Map模拟的二维矩阵List<Map<String, String>>
	 * 例如：[{name0:"Java",name1:"world"}, {name0:"Java1",name1:"world1"}]
	 * 其中：[]对应List,{}对应Map,同时[],和{}对应JavaScript中的数组和对象
	 * 
	 * @throws SQLException
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public static List<Map<String, String>> rs2list(ResultSet rs) throws SQLException {
		if (rs == null) {
			return null;
		}
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		try {
			ResultSetMetaData rsmd = rs.getMetaData();
			int size = rsmd.getColumnCount();
			while (rs.next()) {
				Map<String, String> map = CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(size);
				for (int i = 1; i <= size; i++) {
					String value = StringUtil.fixup(rs.getObject(i));
					// 大写( 和Oracle保持一致 )
					String columnName = rsmd.getColumnName(i).toUpperCase();
					map.put(columnName, value);
				}
				list.add(map);
			}
		} catch (SQLException e) {
			throw e;// 抛出异常，终止此方法执行
		} finally {
			closeResultSet(rs);// 关闭资源，释放游标
		}
		return list;//
	}

	/**
	 * 将ResultSet封装入List和Map模拟的一维矩阵Map<String, String>
	 * {name0:"Java",name1:"world"} 其中：{}对应Java中的Map,{}对应JavaScript中的对象
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public static Map<String, String> rs2map(ResultSet rs) throws SQLException {
		if (rs == null) {
			return null;
		}
		Map<String, String> map = null;
		try {
			if (rs.next()) {// 只取第1条记录
				ResultSetMetaData rsmd = rs.getMetaData();
				int size = rsmd.getColumnCount();
				map = CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(size);
				for (int i = 1; i <= size; i++) {
					String value = StringUtil.fixup(rs.getObject(i));
					// 大写(和Oracle保持一致)
					String columnName = rsmd.getColumnName(i).toUpperCase();
					map.put(columnName, value);
				}
			}
		} catch (SQLException e) {
			throw e;// 抛出异常，终止此方法执行
		} finally {
			closeResultSet(rs);//
		}
		return map;//
	}

	/**
	 * 参rs2map(ResultSet rs)
	 * 
	 * @param object
	 * @return
	 * @throws SQLException
	 */
	public static Map<String, String> rs2map(Object object) throws SQLException {
		if (object instanceof ResultSet) {
			ResultSet rs = (ResultSet) object;
			return rs2map(rs);
		} else {
			return null;
		}
	}

	public static <T> List<T> rs2beans(ResultSet rs, Class<T> beanClass) throws SQLException {
		if (rs == null) {
			return null;
		}
		List<T> beans = null;
		try {
			ResultSetMetaData rsmd = rs.getMetaData();
			int size = rsmd.getColumnCount();
			beans = new ArrayList<T>(size);
			Map<String, Field> fieldMap = ReflectionUtil.getWritableFields(beanClass);
			while (rs.next()) {
				T bean = beanClass.newInstance();
				for (int i = 1; i <= size; i++) {
					Object obj = JdbcUtils.getResultSetValue(rs, i);
					String str = obj == null || obj.toString().equals("null") ? null : obj.toString();
					ReflectionUtil.setFieldValue(fieldMap, bean, rsmd.getColumnName(i), str);
				}
				beans.add(bean);
			}
		} catch (SQLException e) {
			throw e;// 抛出异常，终止此方法执行
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			closeResultSet(rs);// 关闭资源，释放游标
		}

		return beans;
	}

	public static <T> T rs2bean(ResultSet rs, Class<T> beanClass) throws SQLException {
		if (rs == null) {
			return null;
		}
		T bean = null;
		try {
			Map<String, Field> fieldMap = ReflectionUtil.getWritableFields(beanClass);
			if (rs.next()) {// 只取第条记录
				ResultSetMetaData rsmd = rs.getMetaData();
				int size = rsmd.getColumnCount();
				bean = beanClass.newInstance();
				for (int i = 1; i <= size; i++) {
					String str = rs.getObject(i) == null || rs.getObject(i).toString().equals("null") ? null : rs.getObject(i).toString();
					ReflectionUtil.setFieldValue(fieldMap, bean, rsmd.getColumnName(i), str);
				}
			}
		} catch (SQLException e) {
			throw e;// 抛出异常，终止此方法执行
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			closeResultSet(rs);//
		}

		return bean;
	}

	/**
	 * 通过ResultSet组装Bean<br/>
	 * 如：rs:{NAME,BOOK_NO}--->bean:{name,bookNo}或bean:{name,book_no}
	 * 
	 * @param rs
	 * @param bean
	 * @throws SQLException
	 */
	public static void rs2bean(ResultSet rs, Object bean) throws SQLException {
		if (rs == null) {
		}
		try {
			Map<String, Field> fieldMap = ReflectionUtil.getWritableFields(bean.getClass());
			if (rs.next()) {// 只取第条记录
				ResultSetMetaData rsmd = rs.getMetaData();
				int size = rsmd.getColumnCount();
				for (int i = 1; i <= size; i++) {
					String str = rs.getObject(i) == null || rs.getObject(i).toString().equals("null") ? null : rs.getObject(i).toString();
					ReflectionUtil.setFieldValue(fieldMap, bean, rsmd.getColumnName(i), str);
				}
			}
		} catch (SQLException e) {
			throw e;// 抛出异常，终止此方法执行
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			closeResultSet(rs);//
		}
	}

	/**
	 * Close a <code>ResultSet</code>, avoid closing if null.
	 */
	public static void closeResultSet(ResultSet rs) throws SQLException {
		if (rs != null) {
			rs.close();
		}
	}

	/**
	 * Close a <code>Statement</code>, avoid closing if null.
	 */
	public static void closeStatement(Statement stat) throws SQLException {
		if (stat != null) {
			stat.close();
		}
	}

	/**
	 * 
	 * @return
	 */
	public static JdbcTemplate getJdbcTemplate() {
		ApplicationContext applicationContext = ContextUtil.getWebApplicationContext();
		JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
		return jdbcTemplate;
	}
}
